import { AudioClip, AudioSource, assetManager, warn } from "cc";

/**
 * 音频播放
 * @author xiaoyi
 */
export default class AudiosManager {

    protected static audioSourceList: Map<string, AudioSource> = new Map()
    /**当前是否可以播放音乐 */
    static isStop: boolean = false;

    private static loadAudioAsset(audiosPath: string): Promise<AudioClip> {
        return new Promise<AudioClip>((resolve, reject) => {
            if (this.isURL(audiosPath)) {
                assetManager.loadRemote(audiosPath, (error: Error, clip: AudioClip) => {
                    if (error) {
                        reject(error);
                    } else {
                        resolve(clip)
                    }
                });
            } else {
                assetManager.resources.load(audiosPath, null, (error: Error, clip: AudioClip) => {
                    if (error) {
                        warn(error);
                        reject(error);
                    } else {
                        resolve(clip)
                    }
                });
            }
        })
    }

    private static isURL(str: string): boolean {
        const urlPattern = /^(?:\w+:)?\/\/([^\s.]+\.\S{2}|localhost[:?\d]*)\S*$/;
        return urlPattern.test(str);
    }

    /**
     * 播放音乐
     * @param audiosPath 音频路径
     * @param loop 播放次数0为循环播放
     * @param volume 音量
     * @returns 
     */
    public static async play(audiosPath: string, loop: number = 1, volume: number = 1) {
        if (this.isStop) return;
        let audioSourceObj = this.audioSourceList.get(audiosPath);
        if (!audioSourceObj) {
            let clip = await this.loadAudioAsset(audiosPath)
            audioSourceObj = new AudioSource()
            audioSourceObj.clip = clip
            this.audioSourceList.set(audiosPath, audioSourceObj)
        }
        audioSourceObj.volume = volume
        audioSourceObj.loop = loop === 0 ? true : false
        audioSourceObj.play()
        await new Promise<void>((resolve, reject) => {
            setTimeout(() => {
                resolve()
            }, audioSourceObj.duration * 1000)
        })
    }

    /**
     * 预加载音频
     * @param audiosPath 音频所处的位置 
     * @returns 
     */
    public static preLoadAudio(audiosPath: string) {
        if (this.audioSourceList.has(audiosPath)) {
            return;
        }
        if (this.isURL(audiosPath)) {
            assetManager.loadRemote(audiosPath, null, (error: Error, clip: AudioClip) => {
                if (error) {
                    warn(error);
                } else {
                    let audioSourceObj = new AudioSource()
                    audioSourceObj.clip = clip
                    this.audioSourceList.set(audiosPath, audioSourceObj)
                }
            });
        } else {
            assetManager.resources.preload(audiosPath, AudioClip);
        }
    }

    public static stop(audiosPath: string): void {
        let audioSourceObj = this.audioSourceList.get(audiosPath);
        if (audioSourceObj !== undefined) {
            audioSourceObj.stop();
        }
    }

    /**音乐是否播放中 */
    public static isPlaying(audiosPath: string): boolean {
        let audioSourceObj = this.audioSourceList.get(audiosPath);
        if (audioSourceObj !== undefined) {
            if (audioSourceObj.state === 1) {
                return true
            }
        }
        return false;
    }

    public static stopAll(): void {
        this.audioSourceList.forEach((obj) => {
            obj.stop()
        })
    }

    public static getAudioSourceObj(audiosPath: string): AudioSource {
        return this.audioSourceList.get(audiosPath)
    }

    public static getAudioClipObj(audiosPath: string): AudioClip {
        return this.audioSourceList.get(audiosPath).clip
    }
}
